/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.saber.certificacao.beansjsf.prova;

import br.com.saber.certificacao.beansjsf.interfacebean.BeanJSFInterface;
import br.com.saber.certificacao.beansjsf.login.LoginManager;
import br.com.saber.certificacao.beansjsf.semescopo.SelectItemManager;
import br.com.saber.certificacao.ejbs.stateless.interfaces.ProvaBeanLocal;
import br.com.saber.certificacao.ejbs.stateless.interfaces.VersaoBeanLocal;
import br.com.saber.certificacao.enums.Linguagem;
import br.com.saber.certificacao.enums.TipoProva;
import br.com.saber.certificacao.modelos.Certificacao;
import br.com.saber.certificacao.modelos.Prova;
import br.com.saber.certificacao.modelos.Versao;
import br.com.saber.certificacao.modelos.validadores.exceptions.generica.ValidacaoExcecao;
import br.com.saber.certificacao.observador.ControleObserver;
import br.com.saber.certificacao.utils.ParametrosContexto;
import br.com.saber.certificacao.utils.UtilMetodos;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import org.apache.commons.lang.StringUtils;

/**
 *
 * @author gbvbahia
 */
@ManagedBean(name = "provaCriacaoManager")
@ViewScoped
public class ProvaCriacaoManager implements BeanJSFInterface, Observer {

    @EJB
    private VersaoBeanLocal versaoBean;

    @EJB
    private ProvaBeanLocal provaBean;

    @ManagedProperty("#{loginManager}")
    private LoginManager loginManager;

    @ManagedProperty("#{selectItemManager}")
    private SelectItemManager selectItemManager;

    public static final String TODAS_QUESTOES = "todas";

    private boolean provaPendente;

    private Prova provaCadastro;
    
    private TipoProva tipoProva;
    
    private Certificacao certificacaoProva;

    private Versao versaoProva;
    
    private boolean somenteMother = true;

    //Utilizado no painel lateral
    private Long totalQuestoesVersao = 0l;

    //Utilizado no painel lateral
    private Long questoesPortugues = 0l;

    //Utilizado no painel lateral
    private Long questoesIngles = 0l;

    private Integer qtdadeQuestoesProva;

    private Linguagem linguagemQuestoes;

    //Somente para negocio interno
    private Long maxQuestoes;
    
    //Somente para negocio interno
    private Long minQuestoes;

    /** Creates a new instance of ProvaCriacaoManager */
    public ProvaCriacaoManager() {
    }

    //====================
    // Iniciadores
    //====================
    @Override
    @PostConstruct
    public void init() {
        clean();
        maxQuestoes = new Long(ParametrosContexto.getParameterContexto(ParametrosContexto.QUANTIDADE_MAXIMA_QUESTOES_PROVA, FacesContext.getCurrentInstance()));
        minQuestoes = new Long(ParametrosContexto.getParameterContexto(ParametrosContexto.QUANTIDADE_MINIMA_QUESTOES_PROVA, FacesContext.getCurrentInstance()));
        ControleObserver.addBeanObserver(loginManager.getUsuario(), this);
        Logger.getLogger(this.getClass().getName()).log(Level.FINEST, "ProvaCriacaoManager.init() executado!");
    }

    @Override
    @PreDestroy
    public void end() {
        ControleObserver.removeBeanObserver(this.loginManager.getUsuario(), this);
        Logger.getLogger(this.getClass().getName()).log(Level.FINEST, "ProvaCriacaoManager.end() executado!");
    }
    //====================
    //Métodos de Negócio
    //====================

    public void criarProva(ActionEvent event) {
        try {
            this.provaBean.criarProvaParaUsuario(loginManager.getUsuario(), qtdadeQuestoesProva, linguagemQuestoes, versaoProva,tipoProva);
            ControleObserver.notificaObservers(loginManager.getUsuario(), new String[]{ControleObserver.Eventos.PROVA_CRIACAO});
        } catch (ValidacaoExcecao e) {
            if (!StringUtils.isBlank(e.getAtributoName())) {
                UtilMetodos.messageFactoringFull(UtilMetodos.getResourceBundle(e.getMessage(), FacesContext.getCurrentInstance()), null, e.getAtributoName(), FacesMessage.SEVERITY_ERROR, FacesContext.getCurrentInstance());
            } else {
                UtilMetodos.messageFactoringFull(e.getMessage(), FacesMessage.SEVERITY_ERROR, FacesContext.getCurrentInstance());
            }
        }
    }

    /**
     * Reseta o contador de questões por versão, de acordo com a versão escolhida.
     */
    private void atualizaVersaoProva() {
        this.questoesIngles = versaoBean.contarQuestoesDaVersao(versaoProva, Linguagem.INGLES);
        this.questoesPortugues = versaoBean.contarQuestoesDaVersao(versaoProva, Linguagem.PORTUGUES);
        this.totalQuestoesVersao = this.questoesIngles + this.questoesPortugues;
        this.provaCadastro.setVersaoNome(this.versaoProva.getNome());
        this.provaCadastro.setNotaParaPassar(versaoProva.getNotaParaPassar());
        atualizarQuantidadeQuestoes();
    }

    /**
     * Reseta o formulário para não selecionar uma versão fora da certificação
     */
    private void atualizaCertificacaoProva() {
        this.provaCadastro.setCertificacao(this.certificacaoProva.getNome());
        this.versaoProva = null;
        atualizarQuantidadeQuestoes();
    }

    private void atualizarQuantidadeQuestoes() {
        maxQuestoes = new Long(ParametrosContexto.getParameterContexto(ParametrosContexto.QUANTIDADE_MAXIMA_QUESTOES_PROVA, FacesContext.getCurrentInstance()));
        minQuestoes = new Long(ParametrosContexto.getParameterContexto(ParametrosContexto.QUANTIDADE_MINIMA_QUESTOES_PROVA, FacesContext.getCurrentInstance()));
        provaCadastro.setTipoProva(null);
        linguagemQuestoes = null;
        if (this.totalQuestoesVersao != null && maxQuestoes > this.totalQuestoesVersao) {
            maxQuestoes = this.totalQuestoesVersao;
        }
    }

    /**
     * Inicializa as variáveis com valores iniciais.
     * @throws NumberFormatException 
     */
    public void clean() throws NumberFormatException {
        provaCadastro = new Prova();
        provaPendente = !(provaBean.buscarProvaPorStatus(loginManager.getUsuario(), false).isEmpty());
        this.certificacaoProva = null;
        this.versaoProva = null;
        this.qtdadeQuestoesProva = null;
        this.linguagemQuestoes = null;
        this.tipoProva = null;
    }

    /**
     * Ouvinte para quando houver um aviso que este usuário terminou uma
     * prova ele liberar o cadastro de uma nova prova.
     * @param o Normalmente este objeto será nulo.
     * @param arg Sempre será um array de Strings com o nome(s) do(s) evento(s)
     * disparado(s).
     */
    @Override
    public void update(Observable o, Object arg) {
        String[] args = (String[]) arg;
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals(ControleObserver.Eventos.PROVA_TERMINO) || args[i].equals(ControleObserver.Eventos.PROVA_CRIACAO)) {
                provaPendente = !(provaBean.buscarProvaPorStatus(loginManager.getUsuario(), false).isEmpty());
                clean();
            }
        }
    }

    //====================
    //Table Actions
    //====================
    //====================
    //SelectItem
    //====================
    public List<SelectItem> getCertificacoesItens() {
        int questoesQtdade = Integer.valueOf(ParametrosContexto.getParameterContexto(ParametrosContexto.QUANTIDADE_MINIMA_QUESTOES_CERTIFICACAO, FacesContext.getCurrentInstance()));
        return selectItemManager.getCertificacoes(questoesQtdade);
    }

    public List<SelectItem> getVersoesItens() {
        int questoesQtdade = Integer.valueOf(ParametrosContexto.getParameterContexto(ParametrosContexto.QUANTIDADE_MINIMA_QUESTOES_CERTIFICACAO, FacesContext.getCurrentInstance()));
        return selectItemManager.getVersoes(questoesQtdade, certificacaoProva, somenteMother);
    }

    public List<SelectItem> getTipoProvaItens() {
        return selectItemManager.getTipoProva(TipoProva.COMENTADA);
    }

    public List<SelectItem> getLinguagemItens() {
        return selectItemManager.getLinguagens();
    }

    public List<SelectItem> getQuantidadeQuestoes() {
        return selectItemManager.getQuantidade(minQuestoes.intValue(), maxQuestoes.intValue());
    }

    //=========================
    //Getters AND Setters
    //=========================
    public LoginManager getLoginManager() {
        return loginManager;
    }

    public void setLoginManager(LoginManager loginManager) {
        this.loginManager = loginManager;
    }

    public SelectItemManager getSelectItemManager() {
        return selectItemManager;
    }

    public void setSelectItemManager(SelectItemManager selectItemManager) {
        this.selectItemManager = selectItemManager;
    }

    public boolean isProvaPendente() {
        return provaPendente;
    }

    public void setProvaPendente(boolean provaPendente) {
        this.provaPendente = provaPendente;
    }

    public Prova getProvaCadastro() {
        return provaCadastro;
    }

    public void setProvaCadastro(Prova provaCadastro) {
        this.provaCadastro = provaCadastro;
    }

    public Certificacao getCertificacaoProva() {
        return certificacaoProva;
    }

    public void setCertificacaoProva(Certificacao certificacaoProva) {
        this.certificacaoProva = certificacaoProva;
        if(certificacaoProva != null)
        this.atualizaCertificacaoProva(); //*** Negócio ***
    }

    public Versao getVersaoProva() {
        return versaoProva;
    }

    public void setVersaoProva(Versao versaoProva) {
        this.versaoProva = versaoProva;
        if(versaoProva != null)
        this.atualizaVersaoProva(); //*** Negócio ***
    }

    public Long getQuestoesIngles() {
        if(this.versaoProva == null) return 0l;
        return questoesIngles;
    }

    public void setQuestoesIngles(Long questoesIngles) {
        this.questoesIngles = questoesIngles;
    }

    public Long getQuestoesPortugues() {
        if(this.versaoProva == null) return 0l;
        return questoesPortugues;
    }

    public void setQuestoesPortugues(Long questoesPortugues) {
        this.questoesPortugues = questoesPortugues;
    }

    public Long getTotalQuestoesVersao() {
        if(this.versaoProva == null) return 0l;
        return totalQuestoesVersao;
    }

    public void setTotalQuestoesVersao(Long totalQuestoesVersao) {
        this.totalQuestoesVersao = totalQuestoesVersao;
    }

    public Linguagem getLinguagemQuestoes() {
        return linguagemQuestoes;
    }

    public void setLinguagemQuestoes(Linguagem linguagemQuestoes) {
        this.linguagemQuestoes = linguagemQuestoes;
    }

    public Integer getQtdadeQuestoesProva() {
        return qtdadeQuestoesProva;
    }

    public void setQtdadeQuestoesProva(Integer qtdadeQuestoesProva) {
        this.qtdadeQuestoesProva = qtdadeQuestoesProva;
    }

    public TipoProva getTipoProva() {
        return tipoProva;
    }

    public void setTipoProva(TipoProva tipoProva) {
        this.tipoProva = tipoProva;
    }

    public boolean isSomenteMother() {
        return somenteMother;
    }

    public void setSomenteMother(boolean somenteMother) {
        this.somenteMother = somenteMother;
    }
}
